﻿<template>
  <section class="admin-view">
    <header class="page-header">
      <div>
        <h2>管理工作台</h2>
        <p>维护站点的食谱、指南和用户健康档案。</p>
      </div>
      <ElTag type="success">管理员</ElTag>
    </header>

    <ElTabs v-model="activeTab">
      <ElTabPane label="食谱管理" name="recipes">
        <div class="toolbar">
          <ElButton type="primary" @click="openRecipeDialog()">新建食谱</ElButton>
        </div>
        <ElTable :data="recipes" border stripe>
          <ElTableColumn prop="name" label="食谱名称" min-width="160" />
          <ElTableColumn prop="calories" label="热量" width="100">
            <template #default="{ row }">{{ row.calories }} kcal</template>
          </ElTableColumn>
          <ElTableColumn label="标签" min-width="160">
            <template #default="{ row }">
              <ElTag v-for="tag in row.tags" :key="tag" class="tag">{{ tag }}</ElTag>
            </template>
          </ElTableColumn>
          <ElTableColumn label="操作" width="160">
            <template #default="{ row }">
              <ElSpace>
                <ElButton type="primary" link @click="openRecipeDialog(row)">编辑</ElButton>
                <ElButton type="danger" link @click="confirmDeleteRecipe(row.id)">删除</ElButton>
              </ElSpace>
            </template>
          </ElTableColumn>
        </ElTable>
      </ElTabPane>

      <ElTabPane label="指南管理" name="guides">
        <div class="toolbar">
          <ElButton type="primary" @click="openGuideDialog()">新建指南</ElButton>
        </div>
        <ElTable :data="guides" border stripe>
          <ElTableColumn prop="title" label="标题" min-width="200" />
          <ElTableColumn prop="icon" label="图标" width="120" />
          <ElTableColumn prop="image" label="封面" width="160">
            <template #default="{ row }">
              <img v-if="row.image" :src="row.image" alt="" class="guide-thumb" />
              <span v-else class="placeholder">未上传</span>
            </template>
          </ElTableColumn>
          <ElTableColumn label="要点" min-width="220">
            <template #default="{ row }">
              <ul class="tips">
                <li v-for="tip in row.tips" :key="tip">{{ tip }}</li>
              </ul>
            </template>
          </ElTableColumn>
          <ElTableColumn label="操作" width="160">
            <template #default="{ row }">
              <ElSpace>
                <ElButton type="primary" link @click="openGuideDialog(row)">编辑</ElButton>
                <ElButton type="danger" link @click="confirmDeleteGuide(row.id)">删除</ElButton>
              </ElSpace>
            </template>
          </ElTableColumn>
        </ElTable>
      </ElTabPane>

      <ElTabPane label="健康档案" name="health">
        <div class="toolbar">
          <ElButton type="primary" @click="refreshHealth">刷新</ElButton>
        </div>
        <ElTable :data="healthProfiles" border stripe>
          <ElTableColumn prop="name" label="姓名" min-width="160" />
          <ElTableColumn prop="email" label="邮箱" min-width="220" />
          <ElTableColumn prop="height" label="身高(cm)" width="120" />
          <ElTableColumn prop="weight" label="体重(kg)" width="120" />
          <ElTableColumn prop="bmi" label="BMI" width="90" />
          <ElTableColumn prop="bmr" label="BMR" width="90" />
          <ElTableColumn label="操作" width="160">
            <template #default="{ row }">
              <ElSpace>
                <ElButton type="primary" link @click="openHealthDialog(row)">编辑</ElButton>
              </ElSpace>
            </template>
          </ElTableColumn>
        </ElTable>
      </ElTabPane>

      <ElTabPane label="用户权限" name="users">
        <ElTable :data="users" border stripe>
          <ElTableColumn prop="name" label="姓名" min-width="160" />
          <ElTableColumn prop="email" label="邮箱" min-width="220" />
          <ElTableColumn label="权限" width="160">
            <template #default="{ row }">
              <ElSelect v-model="row.role" size="small" @change="(value) => updateUserRole(row.id, value)">
                <ElOption label="普通用户" value="user" />
                <ElOption label="管理员" value="admin" />
              </ElSelect>
            </template>
          </ElTableColumn>
          <ElTableColumn label="操作" width="140">
            <template #default="{ row }">
              <ElButton type="danger" link @click="confirmDeleteUser(row.id)">删除</ElButton>
            </template>
          </ElTableColumn>
        </ElTable>
      </ElTabPane>
    </ElTabs>

    <!-- 食谱弹窗 -->
    <ElDialog v-model="recipeDialog.visible" :title="recipeDialog.title" width="560px" @closed="resetRecipeForm">
      <ElForm :model="recipeForm" label-width="100px">
        <ElFormItem label="名称">
          <ElInput v-model="recipeForm.name" placeholder="请输入食谱名称" />
        </ElFormItem>
        <ElFormItem label="热量">
          <ElInputNumber v-model="recipeForm.calories" :min="50" :max="1200" />
        </ElFormItem>
        <ElFormItem label="标签">
          <ElInput v-model="recipeForm.tags" placeholder="逗号分隔，如：低GI, 早餐" />
        </ElFormItem>
        <ElFormItem label="封面图">
          <div class="file-input-row">
            <ElInput v-model="recipeForm.image" placeholder="可填写图片地址或上传" />
            <ElButton type="primary" plain size="small" :loading="imageUploading" @click="triggerRecipeImageSelect">
              上传图片
            </ElButton>
          </div>
          <input ref="recipeImageInput" type="file" accept="image/*" class="hidden-file-input" @change="handleRecipeImageSelected" />
        </ElFormItem>
        <ElFormItem label="配料">
          <ElInput
            v-model="recipeForm.ingredients"
            type="textarea"
            :rows="4"
            placeholder="每行一种食材，如：鸡胸肉 120 克"
          />
        </ElFormItem>
        <ElFormItem label="烹饪步骤">
          <ElInput v-model="recipeForm.method" type="textarea" :rows="4" placeholder="分步骤简要说明" />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElSpace>
          <ElButton @click="recipeDialog.visible = false">取消</ElButton>
          <ElButton type="primary" :loading="saving" @click="saveRecipe">保存</ElButton>
        </ElSpace>
      </template>
    </ElDialog>

    <!-- 指南弹窗 -->
    <ElDialog v-model="guideDialog.visible" :title="guideDialog.title" width="520px" @closed="resetGuideForm">
      <ElForm :model="guideForm" label-width="100px">
        <ElFormItem label="标题">
          <ElInput v-model="guideForm.title" placeholder="请输入指南标题" />
        </ElFormItem>
        <ElFormItem label="图标">
          <ElSelect v-model="guideForm.icon" placeholder="选择图标">
            <ElOption label="Data" value="data" />
            <ElOption label="Guide" value="guide" />
            <ElOption label="Edit" value="edit" />
            <ElOption label="Coffee" value="coffee" />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="封面图">
          <div class="file-input-row">
            <ElInput v-model="guideForm.image" placeholder="可填写图片地址或上传" />
            <ElButton type="primary" plain size="small" :loading="guideImageUploading" @click="triggerGuideImageSelect">
              上传图片
            </ElButton>
          </div>
          <input ref="guideImageInput" type="file" accept="image/*" class="hidden-file-input" @change="handleGuideImageSelected" />
        </ElFormItem>
        <ElFormItem label="要点">
          <ElInput
            v-model="guideForm.tips"
            type="textarea"
            :rows="4"
            placeholder="每行一个要点"
          />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElSpace>
          <ElButton @click="guideDialog.visible = false">取消</ElButton>
          <ElButton type="primary" :loading="saving" @click="saveGuide">保存</ElButton>
        </ElSpace>
      </template>
    </ElDialog>

    <!-- 健康档案弹窗 -->
    <ElDialog v-model="healthDialog.visible" title="编辑健康档案" width="480px" @closed="resetHealthForm">
      <ElForm :model="healthForm" label-width="100px">
        <ElFormItem label="身高 (cm)">
          <ElInputNumber v-model="healthForm.height" :min="80" :max="250" :precision="1" :step="0.5" />
        </ElFormItem>
        <ElFormItem label="体重 (kg)">
          <ElInputNumber v-model="healthForm.weight" :min="25" :max="200" :precision="1" :step="0.5" />
        </ElFormItem>
        <ElFormItem label="性别">
          <ElSelect v-model="healthForm.gender">
            <ElOption label="男" value="male" />
            <ElOption label="女" value="female" />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="年龄">
          <ElInputNumber v-model="healthForm.age" :min="12" :max="90" />
        </ElFormItem>
        <ElFormItem label="目标">
          <ElInput v-model="healthForm.goal" type="textarea" :rows="3" />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElSpace>
          <ElButton @click="healthDialog.visible = false">取消</ElButton>
          <ElButton type="primary" :loading="saving" @click="saveHealth">保存</ElButton>
        </ElSpace>
      </template>
    </ElDialog>
  </section>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import {
  ElTabs,
  ElTabPane,
  ElTable,
  ElTableColumn,
  ElButton,
  ElTag,
  ElDialog,
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElSelect,
  ElOption,
  ElSpace,
  ElCard,
  ElRow,
  ElCol,
  ElMessage,
} from 'element-plus';
import apiClient from '../services/api';
import { useContentStore, type Recipe, type WellnessGuide, type AdminUser, type UserProfile } from '../stores/content';

const contentStore = useContentStore();
const { recipes, guides, users, healthProfiles } = storeToRefs(contentStore);

const activeTab = ref('recipes');
const saving = ref(false);
const imageUploading = ref(false);
const guideImageUploading = ref(false);

const recipeDialog = reactive({ visible: false, editingId: null as string | null, title: '新建食谱' });
const guideDialog = reactive({ visible: false, editingId: null as string | null, title: '新建指南' });
const healthDialog = reactive({ visible: false, editingUserId: null as string | null });

const recipeForm = reactive({
  name: '',
  calories: 320,
  tags: '',
  image: '',
  ingredients: '',
  method: '',
});

const guideForm = reactive({
  title: '',
  icon: 'guide',
  image: '',
  tips: '',
});

const healthForm = reactive({
  userId: '',
  height: null as number | null,
  weight: null as number | null,
  gender: 'female',
  age: null as number | null,
  goal: '',
});

const recipeImageInput = ref<HTMLInputElement | null>(null);
const guideImageInput = ref<HTMLInputElement | null>(null);

const parseTags = (input: string) =>
  input.split(',').map((tag) => tag.trim()).filter(Boolean);

const parseIngredients = (input: string) =>
  input
    .split('\n')
    .map((line) => line.trim())
    .filter(Boolean)
    .map((line) => {
      const [name, ...rest] = line.split(/\s+/);
      return { name, amount: rest.join(' ') || '' };
    })
    .filter((item) => item.name);

const parseTips = (input: string) =>
  input.split('\n').map((tip) => tip.trim()).filter(Boolean);

const resetRecipeForm = () => {
  recipeDialog.editingId = null;
  recipeDialog.title = '新建食谱';
  recipeForm.name = '';
  recipeForm.calories = 320;
  recipeForm.tags = '';
  recipeForm.image = '';
  recipeForm.ingredients = '';
  recipeForm.method = '';
};

const resetGuideForm = () => {
  guideDialog.editingId = null;
  guideDialog.title = '新建指南';
  guideForm.title = '';
  guideForm.icon = 'guide';
  guideForm.image = '';
  guideForm.tips = '';
};

const resetHealthForm = () => {
  healthDialog.editingUserId = null;
  healthForm.userId = '';
  healthForm.height = null;
  healthForm.weight = null;
  healthForm.gender = 'female';
  healthForm.age = null;
  healthForm.goal = '';
};

const openRecipeDialog = (recipe?: Recipe) => {
  if (recipe) {
    recipeDialog.editingId = recipe.id;
    recipeDialog.title = '编辑食谱';
    recipeForm.name = recipe.name;
    recipeForm.calories = recipe.calories;
    recipeForm.tags = recipe.tags.join(',');
    recipeForm.image = recipe.image;
    recipeForm.ingredients = recipe.ingredients
      .map((item) => {
        const amount = item.amount ? ` · ${item.amount}` : '';
        return `${item.name}${amount}`;
      })
      .join('\n');
    recipeForm.method = recipe.method;
  } else {
    resetRecipeForm();
  }
  recipeDialog.visible = true;
};

const openGuideDialog = (guide?: WellnessGuide) => {
  if (guide) {
    guideDialog.editingId = guide.id;
    guideDialog.title = '编辑指南';
    guideForm.title = guide.title;
    guideForm.icon = guide.icon;
    guideForm.image = guide.image;
    guideForm.tips = guide.tips.join('\n');
  } else {
    resetGuideForm();
  }
  guideDialog.visible = true;
};

const openHealthDialog = (row: any) => {
  healthDialog.editingUserId = row.userId || row.id;
  healthForm.userId = healthDialog.editingUserId;
  healthForm.height = row.height ?? null;
  healthForm.weight = row.weight ?? null;
  healthForm.gender = row.gender ?? 'female';
  healthForm.age = row.age ?? null;
  healthForm.goal = row.goal ?? '';
  healthDialog.visible = true;
};

const triggerRecipeImageSelect = () => recipeImageInput.value?.click();
const triggerGuideImageSelect = () => guideImageInput.value?.click();

const handleImageUpload = async (event: Event, targetRef: typeof imageUploading, assign: (path: string) => void) => {
  const input = event.target as HTMLInputElement;
  const file = input.files?.[0];
  if (!file) return;
  if (!file.type.startsWith('image/')) {
    ElMessage.warning('请选择图片文件');
    input.value = '';
    return;
  }
  const formData = new FormData();
  formData.append('file', file);
  targetRef.value = true;
  try {
    const { data } = await apiClient.post<{ path: string; url?: string }>(
      '/media/upload',
      formData,
      { headers: { 'Content-Type': 'multipart/form-data' } },
    );
    assign(data.url ?? data.path ?? '');
    ElMessage.success('图片上传成功');
  } catch (error) {
    ElMessage.error('图片上传失败，请稍后再试');
  } finally {
    targetRef.value = false;
    input.value = '';
  }
};

const handleRecipeImageSelected = (event: Event) => handleImageUpload(event, imageUploading, (path) => {
  recipeForm.image = path;
});

const handleGuideImageSelected = (event: Event) => handleImageUpload(event, guideImageUploading, (path) => {
  guideForm.image = path;
});

const saveRecipe = async () => {
  if (!recipeForm.name || !recipeForm.calories || !recipeForm.method) {
    ElMessage.warning('请完整填写食谱信息');
    return;
  }
  saving.value = true;
  const payload = {
    name: recipeForm.name,
    calories: recipeForm.calories,
    tags: parseTags(recipeForm.tags),
    image: recipeForm.image,
    ingredients: parseIngredients(recipeForm.ingredients),
    method: recipeForm.method,
  };
  try {
    if (recipeDialog.editingId) {
      await contentStore.updateRecipe(recipeDialog.editingId, payload);
      ElMessage.success('食谱已更新');
    } else {
      await contentStore.createRecipe(payload as Omit<Recipe, 'id'>);
      ElMessage.success('食谱已创建');
    }
    recipeDialog.visible = false;
  } catch (error) {
    ElMessage.error('保存失败，请稍后重试');
  } finally {
    saving.value = false;
  }
};

const saveGuide = async () => {
  if (!guideForm.title || !guideForm.image) {
    ElMessage.warning('请填写完整信息');
    return;
  }
  saving.value = true;
  const payload = {
    title: guideForm.title,
    icon: guideForm.icon,
    image: guideForm.image,
    tips: parseTips(guideForm.tips),
  };
  try {
    if (guideDialog.editingId) {
      await contentStore.updateGuide(guideDialog.editingId, payload);
      ElMessage.success('指南已更新');
    } else {
      await contentStore.createGuide(payload as Omit<WellnessGuide, 'id'>);
      ElMessage.success('指南已创建');
    }
    guideDialog.visible = false;
  } catch (error) {
    ElMessage.error('保存失败，请稍后重试');
  } finally {
    saving.value = false;
  }
};

const saveHealth = async () => {
  if (!healthDialog.editingUserId) return;
  saving.value = true;
  try {
    await contentStore.updateHealthProfile(healthDialog.editingUserId, {
      height: healthForm.height,
      weight: healthForm.weight,
      gender: healthForm.gender as 'male' | 'female',
      age: healthForm.age,
      goal: healthForm.goal,
    });
    ElMessage.success('健康档案已更新');
    healthDialog.visible = false;
  } catch (error) {
    ElMessage.error('保存失败，请稍后重试');
  } finally {
    saving.value = false;
  }
};

const confirmDeleteRecipe = async (id: string) => {
  await contentStore.deleteRecipe(id);
  ElMessage.success('已删除食谱');
};

const confirmDeleteGuide = async (id: string) => {
  await contentStore.deleteGuide(id);
  ElMessage.success('已删除指南');
};

const updateUserRole = async (id: string, role: 'user' | 'admin') => {
  await contentStore.updateUserRole(id, role);
  ElMessage.success('权限已更新');
};

const refreshHealth = async () => {
  await contentStore.fetchHealthProfiles();
};

const confirmDeleteUser = async (id: string) => {
  try {
    await contentStore.deleteUser(id);
    ElMessage.success('用户已删除');
  } catch (error: any) {
    ElMessage.error(error?.response?.data?.message ?? '删除失败，请稍后重试');
  }
};

onMounted(async () => {
  await Promise.all([contentStore.fetchUsers(), refreshHealth()]);
});
</script>

<style scoped>
.admin-view {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

.toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.tag {
  margin-right: 6px;
}

.tips {
  margin: 0;
  padding-left: 18px;
}

.file-input-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.hidden-file-input {
  display: none;
}

.guide-thumb {
  width: 96px;
  height: 64px;
  object-fit: cover;
  border-radius: 8px;
}

.placeholder {
  color: var(--mint-text-muted);
  font-size: 12px;
}
</style>
